
package GUI;

import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;

import command.Command;
import command.CommandType;

import concept.Effect;
import concept.RegenerationEffect;
import controller.CommandManager;
import controller.LocalManager;

import utilities.RefreshListener;
import utilities.ResultEvent;
import utilities.ResultListener;
import utilities.SpringUtilities;
import Player.PG;
import gdrObject.*;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Inventory extends JPanel implements ResultListener{
	
	public Inventory(RefreshListener refresh){
        this.player = LocalManager.getCurrentPlayer();
        this.refresh = refresh;
        this.setLayout(new BorderLayout());
        commManager = new CommandManager();
        commManager.addResultListener(this);
        JLabel label = new JLabel("Inventory");
        JPanel p = new JPanel();
        p.add(label);
        p.setOpaque(true);
        p.setBackground(new Color(160, 180, 200));
        
        JPanel globalPanel = new JPanel();
        globalPanel.setLayout(new BoxLayout(globalPanel, BoxLayout.Y_AXIS));
        globalPanel.add(createPanelAttDef());
        globalPanel.add(createPanelBackPack());
        this.add(p, BorderLayout.NORTH);
        this.add(globalPanel, BorderLayout.CENTER);
        
    }

    public JPanel createPanelAttDef(){
        JLabel label = new JLabel("Statistiche Combattimento");
        JPanel p = new JPanel();
        p.add(label);
        p.setOpaque(true);
        p.setBackground(new Color(200, 180, 160));
        equippedWeapon = new JTextField();
        Weapon w = player.getEquippedWeapon();
        if(w!=null)
            equippedWeapon.setText(w.getName());
        else
            equippedWeapon.setText("nessuna arma equip.");
        equippedArmor = new JTextField();
        Armor a = player.getEquippedArmor();
        if(a!=null)
            equippedArmor = new JTextField(a.getName());
        else
            equippedArmor.setText("nessuna armatura equip.");
        equippedWeapon.setOpaque(false); equippedWeapon.setEditable(false);
        equippedArmor.setOpaque(false); equippedArmor.setEditable(false);
        packAwayWeapon = new JButton("Rimuovi");
        packAwayArmor = new JButton("Rimuovi");
        packAwayWeapon.addActionListener(new PackAwayEquippment());
        packAwayArmor.addActionListener(new PackAwayEquippment());
        JPanel panelAttDef = new JPanel(new BorderLayout());
        JPanel panel = new JPanel(new SpringLayout());
        panel.add(equippedWeapon);
        panel.add(packAwayWeapon);
        panel.add(equippedArmor);
        panel.add(packAwayArmor);
        SpringUtilities.makeCompactGrid(panel, 2, 2, 3, 5, 4, 2);
        panelAttDef.add(p, BorderLayout.NORTH);
        panelAttDef.add(panel, BorderLayout.CENTER);
        return panelAttDef;
    }
    
    public JPanel createPanelBackPack(){
        JLabel label = new JLabel("Zaino");
        JPanel p = new JPanel();
        p.add(label);
        p.setOpaque(true);
        p.setBackground(new Color(200, 180, 160));
        
        //Buttons
        JPanel buttons = new JPanel(new GridLayout(4, 1));
        JButton weaponButton = new JButton("Armi");
        weaponButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				CL.show(cardPanel, LABEL_WEAPON);
			}
		});
        JButton armorButton = new JButton("Armature");
        armorButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				CL.show(cardPanel, LABEL_ARMOR);
			}
		});
        JButton usableButton = new JButton("Utilizzabili");
        usableButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				CL.show(cardPanel, LABEL_USABLE);
			}
		});
        JButton miscellaneousButton = new JButton("Varie");
        miscellaneousButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				CL.show(cardPanel, LABEL_MISCELLANEOUS);
			}
		});
		buttons.add(weaponButton);
		buttons.add(armorButton);
		buttons.add(usableButton);
		buttons.add(miscellaneousButton);
        
		//divide back pack items
		final ArrayList<Object[]> weaponData = new ArrayList<Object[]>();
		final ArrayList<Object[]> armorData = new ArrayList<Object[]>();
		final ArrayList<Object[]> usableData = new ArrayList<Object[]>();
		final ArrayList<Object[]> miscellaneousData = new ArrayList<Object[]>();
		Collection<GdrObject> backPack = player.getBackPack();
        Iterator<GdrObject> iter = backPack.iterator();
        GdrObject obj = null;
        for(int i=0; i<backPack.size(); i++){
            obj = iter.next();
            if(obj instanceof Weapon){
                Weapon w = (Weapon)obj;
                String type = w.getClass().getName();
                weaponData.add(new Object[]{w.getName(), type.substring(10, type.length()-6), 
                		w.getRequiredIntelligence(), w.getRequiredStrength(), 
                		w.getRequiredAgility(), w.getRequiredDetermination()});
            }else if(obj instanceof Armor){
                Armor a = (Armor)obj;
                armorData.add(new Object[]{a.getName(), a.getDefence(), 
                		a.getRequiredStrength(), a.getRequiredIntelligence(),
                		a.getRequiredAgility(), a.getRequiredDetermination()});
            }else if(obj instanceof Usable){
            	Usable u = (Usable)obj;
            	Object temp1, temp2, temp3;
            	Effect eff = u.getEffect();
            	if(eff != null){
            		temp1 = eff.getAttributeToModify().name();
            		temp2 = eff.getValue();
            		if(eff.getTemporary())
            			temp3 = eff.getTimes()+" "+eff.getMeasure().name();
            		else
            			temp3 = "Illimitato";
            	}else{
            		RegenerationEffect reg = u.getRegenerationEffect();
            		temp1 = reg.getLifeOrMana().name();
	           		temp2 = reg.getValue();
	           		temp3 = "-";
            	}
            	usableData.add(new Object[]{u.getName(), temp1, temp2, temp3});
            }else{
            	miscellaneousData.add(new Object[]{obj.getName()});
            }
        }
        
        /*-----------Weapon Table------------*/
        String[] columnNamesWeapon = {"Nome", "Tipo", "int", "for", "agi", "det"};
        weaponTable = new JTable(new MyTableModel(weaponData.toArray(new Object[][]{}), columnNamesWeapon)){
			public String getToolTipText(MouseEvent e) {
                String tip = null;
                Point p = e.getPoint();
                int rowIndex = rowAtPoint(p);
                if(rowIndex != -1){
	                TableModel model = getModel();
	                String name = (String)model.getValueAt(rowIndex,0);
	                Weapon weapon = (Weapon)player.getObject(name);
	                tip = weapon.toHTML();
                }
                else
                	tip = super.getToolTipText();
                return tip;
            }
			private static final long serialVersionUID = 674930552651L;
        };
        weaponTable.setFillsViewportHeight(true);
        TableColumn column = null;
        for (int i = 0; i < 6; i++) {
            column = weaponTable.getColumnModel().getColumn(i);
            if (i == 0) {
                column.setPreferredWidth(130);
            } else if(i==1) {
                column.setPreferredWidth(50);
            }else{
            	column.setMaxWidth(25);
            	column.setMinWidth(25);
            }
        }
        weaponTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        weaponTable.getSelectionModel().setLeadSelectionIndex(-1);
        weaponTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				if (e.getValueIsAdjusting() == false) {
					int index = weaponTable.getSelectedRow();
			        if (index != -1) {
			        	commManager.execCommand(new Command(weaponData.get(index)[0].toString(), CommandType.CHANGE), null);
			        }
			        weaponTable.clearSelection();
			        weaponTable.revalidate();
			    }
			}
		});
        JScrollPane scrWeapon = new JScrollPane(weaponTable);
        scrWeapon.setPreferredSize(new Dimension(300, 400));
        
        /*-----------Armor Table------------*/
        String[] columnNamesArmor = {"Nome", "Difesa", "for", "int", "agi", "det"};
        armorTable = new JTable(new MyTableModel(armorData.toArray(new Object[][]{}), columnNamesArmor)){
			public String getToolTipText(MouseEvent e) {
                String tip = null;
                Point p = e.getPoint();
                int rowIndex = rowAtPoint(p);
                if(rowIndex != -1){
	                TableModel model = getModel();
	                String name = (String)model.getValueAt(rowIndex,0);
	                Armor armor = (Armor)player.getObject(name);
	                tip = armor.toHTML();
                }
                else
                	tip = super.getToolTipText();
                return tip;
            }
			private static final long serialVersionUID = 15465879435L;
        };
        column = null;
        for (int i = 0; i < 6; i++) {
            column = armorTable.getColumnModel().getColumn(i);
            if (i == 0) {
                column.setPreferredWidth(130);
            } else if(i==1) {
                column.setPreferredWidth(50);
            }else{
            	column.setMaxWidth(25);
            	column.setMinWidth(25);
            }
        }
        armorTable.setFillsViewportHeight(true);
        armorTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        armorTable.getSelectionModel().setLeadSelectionIndex(-1);
        armorTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				if (e.getValueIsAdjusting() == false) {
					int index = armorTable.getSelectedRow();
			        if (index != -1) {
			        	commManager.execCommand(new Command(armorData.get(index)[0].toString(), CommandType.CHANGE), null);
			        }
			        armorTable.clearSelection();
			        armorTable.revalidate();
			    }
			}
		});
        JScrollPane scrArmor = new JScrollPane(armorTable);
        scrArmor.setPreferredSize(new Dimension(300, 400));
        
        /*-----------Usable Table------------*/
        String[] columnNamesUsable = {"Nome", "Modifica", "Valore", "Periodo"};
        usableTable = new JTable(new MyTableModel(usableData.toArray(new Object[][]{}), columnNamesUsable)){
			public String getToolTipText(MouseEvent e) {
                String tip = null;
                Point p = e.getPoint();
                int rowIndex = rowAtPoint(p);
                if(rowIndex != -1){
	                TableModel model = getModel();
	                String name = (String)model.getValueAt(rowIndex,0);
	                Usable usable = (Usable)player.getObject(name);
	                tip = usable.toHTML();
                }
                else
                	tip = super.getToolTipText();
                return tip;
            }
			private static final long serialVersionUID = 5638499531111L;
        };
        usableTable.setFillsViewportHeight(true);
        usableTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        usableTable.getSelectionModel().setLeadSelectionIndex(-1);
        usableTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				if (e.getValueIsAdjusting() == false) {
					int index = usableTable.getSelectedRow();
			        if (index != -1) {
			        	commManager.execCommand(new Command(usableData.get(index)[0].toString(), CommandType.USE), null);
			        }
			        usableTable.clearSelection();
			        usableTable.revalidate();
			    }
			}
		});
        JScrollPane scrUsable = new JScrollPane(usableTable);
        scrUsable.setPreferredSize(new Dimension(300, 400));
        
        /*-----------Miscellaneous Table------------*/
        String[] columnNamesMiscellaneous = {"Nome"};
       	miscellaneousTable = new JTable(new MyTableModel(miscellaneousData.toArray(new Object[][]{}), columnNamesMiscellaneous)){
			public String getToolTipText(MouseEvent e) {
                String tip = null;
                Point p = e.getPoint();
                int rowIndex = rowAtPoint(p);
                if(rowIndex != -1){
	                TableModel model = getModel();
	                String name = (String)model.getValueAt(rowIndex,0);
	                GdrObject obj = player.getObject(name);
	                tip = obj.toHTML();
                }
                else
                	tip = super.getToolTipText();
                return tip;
            }
			private static final long serialVersionUID = -424556487918746L;
        };
       	miscellaneousTable.setFillsViewportHeight(true);
       	miscellaneousTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
       	miscellaneousTable.getSelectionModel().setLeadSelectionIndex(-1);
       	miscellaneousTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				if (e.getValueIsAdjusting() == false) {
					int index = miscellaneousTable.getSelectedRow();
			        if (index != -1) {
			        	//commManager.execCommand(new Command(armorData.get(index)[0].toString(), CommandType.CHANGE), player, null);
			        }
			        miscellaneousTable.clearSelection();
			        miscellaneousTable.revalidate();
			    }
			}
		});
        JScrollPane scrMisc = new JScrollPane(miscellaneousTable);
        scrMisc.setPreferredSize(new Dimension(300, 400));
        
        cardPanel = new JPanel(CL);
		cardPanel.add(scrWeapon, LABEL_WEAPON);
		cardPanel.add(scrArmor, LABEL_ARMOR);
		cardPanel.add(scrUsable, LABEL_USABLE);
		cardPanel.add(scrMisc, LABEL_MISCELLANEOUS);
		JPanel panelBackPack = new JPanel(new BorderLayout());
        panelBackPack.add(p, BorderLayout.NORTH);
        panelBackPack.add(buttons, BorderLayout.WEST);
        panelBackPack.add(cardPanel, BorderLayout.EAST);
        return panelBackPack;
    }
    
    public void updateValues(){
    	player.updateVariablesDependingOnAttributes();
        Weapon w = player.getEquippedWeapon();
        if(w!=null)
            equippedWeapon.setText(w.getName());
        else
            equippedWeapon.setText("nessuna arma equip.");
        Armor a = player.getEquippedArmor();
        if(a!=null)
            equippedArmor.setText(a.getName());
        else
            equippedArmor.setText("nessuna armatura equip.");
    }
    
    @Override
	public void stateChanged(ResultEvent event) {
    	switch(event.getType()){
    	case WEAPON_CHANGED:
		case ARMOR_CHANGED:
		case USED:
			refresh.refresh();
			break;
		case ERROR:
			System.err.println("ERROR: "+event.getArgument());
			break;
		default:
			break;
    	}
	}
    
    public class SelectedListener implements ActionListener{
        public void actionPerformed(ActionEvent e) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    public class PackAwayEquippment implements ActionListener{
        public void actionPerformed(ActionEvent e){
            JButton b = (JButton)e.getSource();
            if(b.equals(packAwayWeapon)){
            	commManager.execCommand(new Command("pack weapon", CommandType.CHANGE), null);
            }
            else if(b.equals(packAwayArmor)){
            	commManager.execCommand(new Command("pack armor", CommandType.CHANGE), null);
            }
            refresh.refresh();
        }
    }
    
    class MyTableModel extends AbstractTableModel {
    	private static final long serialVersionUID = 8926154567422070609L;
		private String[] columnNames;
        private Object[][] data;

        public MyTableModel(Object[][] data, String[] columnNames){
        	this.columnNames = columnNames;
        	this.data = data;
        }
        
        public int getColumnCount() {
            return columnNames.length;
        }

        public int getRowCount() {
            return data.length;
        }

        public String getColumnName(int col) {
            return columnNames[col];
        }

        public Object getValueAt(int row, int col) {
            return data[row][col];
        }

		public Class getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }

        public boolean isCellEditable(int row, int col) {
            return false;
        }
    }

    private PG player;
    private CommandManager commManager;
    private JTextField equippedWeapon, equippedArmor;
    private JButton packAwayWeapon, packAwayArmor;
    private JTable weaponTable, armorTable, usableTable, miscellaneousTable;
    private JPanel cardPanel;
    private RefreshListener refresh;
    private static final CardLayout CL = new CardLayout();
    private static final String LABEL_WEAPON = "Weapons", LABEL_USABLE = "Usable", LABEL_ARMOR = "Armor", LABEL_MISCELLANEOUS= "Miscellaneous";
    private static final long serialVersionUID = 1L;
}
